home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-12-30 | 11.9 KB | 329 lines | [TEXT/MPS ] |
- INCLUDE 'SysEqu.a' ;the usual system equates & macros
- INCLUDE 'Traps.a'
- INCLUDE 'QuickEqu.a'
-
- newPtrClear FUNC EXPORT
-
- IMPORT SAVERETA1
-
- MOVE.L (SP)+,A1
- MOVE.L (SP)+,D0
- _NewPtr clear
- MOVE.L A0,(SP)
- JMP SAVERETA1
-
- ENDF
-
-
- Rotate PROC EXPORT
- ;------------------------------------------------------------------------
- ;
- ; PROCEDURE Rotate (sourceMap, destMap : bitMap );
- ;
- ; given a source and destination bitmap rotate it CCW 90°…
- ; bitmap can be of any size, we will align on a word boundaries (v & h)
- ;
- ;-------------------------------------------------------------------------------
- ; a0 = result of _newPtr call | d0 = size of bitMap to allocate
- ; a1 = ptr to src bitMap | d1 = width/2 (source)
- ; a2 = ptr to dest bitMap | d2 = height/2 (source)
- ; a3 = dest bits | d3 = left | top
- ; a4 = copy of dest bits | d4 = ctrPt.h
- ; a5 = not used | d5 = ctrPt.v
- ; a6 = not used | d6 = right | bottom
- ; a7 = not used | d7 = rowBytes of dest bitMap
- ;-------------------------------------------------------------------------------
- ; ***********************************************************************
- ; * *
- ; * Initialize destination bitMap (destMap), etc… *
- ; * *
- ; ***********************************************************************
- ; parameter offsets
- ;
- DestMap EQU 4+4 ; offset to dest bitmap ^
- SourceMap EQU DestMap + 4 ; offset to source bitmap ^
- ;
- ; create local stack frame, and save some registers
- ; make room for dest rect to be passed back
- ;
- link a6,#0 ; set up a stack frame (no bytes)
- movem.l d3-d7/a2-a5,-(sp) ; save registers pascal may need
-
- move.l SourceMap(a6),a1 ; point to the source BitMap
- move.l DestMap(a6),a2 ; point to the dest BitMap
- ;
- ; compute height of source BitMap rounded up to nearest word
- ;
- move.w bounds+bottom(a1),d7; get bottom and put in d7
- sub.w bounds+top(a1),d7 ; bottom - top = height, put in d7
- move.w d7,d0 ; save a copy of height for later
- ; rnd = (height+15)/16, follows:
- addi.w #15,d7 ; add 15 to the height, put in d7
- lsr #4,d7 ; divide by 16
- lsl #1,d7 ; multiply by 2 = rowBytes of dest bitMap
- ;
- ; d7 now contains rowBytes of dest bitMap
- ;
- ; now compute the destRect for dest bitMap
- ;
- ; compute center point of Source rect
- ; note the center points are not necess. the
- ; same in the vert dir. relative to srcMap
- ; because of rounding that follows (i.e. height
- ; of srcMap is dir. prop. to RowBytes of destMap)
- lsr #1,d0 ; divide height by 2
- move.w d0,d2 ; make a copy of height/2 for later
- move.w bounds+top(a1),d5 ; get 'top' of source rect
- add.w d0,d5 ; d5 now contains vert component of ctr pt
- ; compute the width of src rect & put in d4
- move.w bounds+right(a1),d3 ; get right and put in d3
- sub.w bounds+left(a1),d3 ; right - left = width, put in d3
- lsr #1,d3 ; divide width by 2
- move.w d3,d1 ; make a copy of width/2 for later
- move.w bounds+right(a1),d4 ; get right of source rect
- sub.w d3,d4 ; d4 now contains horiz component of ctr pt
- ;
- ; now get center point and compute bounds for dest bitMap
- ; height and width are reversed now for the 2 bitMaps
- ;
- ; left :=ctrPt.h - height/2
- ; top :=ctrPt.v - width/2
- ; right :=ctrPt.h + height/2
- ; bottom:=ctrPt.v + width/2
- ; SetRect(rect, left, top, right, bottom) put data in direct to
- ; avoid the overhead of a trap call
- ;
- ; compute 'top'
- move.w d5,d3 ; get a copy of ctrPt.v and put in d3
- sub.w d1,d3 ; ctrPt.v - width/2 = 'top' in d3
- swap d3 ; move 'top' to hiword
- ; compute 'left'
- move.w d4,d3 ; get a copy of ctrPt.h and put in loword d3
- sub.w d2,d3 ; ctrPt.h - height/2 = 'left' in loword d3
- ;
- ; we now have 'top' in hiword & 'left' in loword d3
- ;
- ; compute 'bottom'
- move.w d5,d6 ; get a copy of ctrPt.v in of d3
- add.w d1,d6 ; ctrPt.v + width/2 = 'bottom' in d3
- swap d6 ; move 'bottom' to hiword
- ; compute 'right'
- move.w d4,d6 ; get a copy of ctrPt.h and put in loword d6
- add.w d2,d6 ; ctrPt.h + height/2 = 'right' in loword d6
- ;
- ; we now have 'bottom' in hiword & 'right' in loword d6
- ;
- ; assign data to dest bitMap structure directly
- ;
- move.w d7,rowBytes(a2) ; put in rowBytes direct for dest bitMap
- move.l d3,bounds+topLeft(a2) ; put the coord pair in direct
- move.l d6,bounds+botRight(a2) ; put the coord pair in direct
- move.w d7,d0 ; put rowbytes in d0
- mulu rowBytes(a1),d0 ; multiply rowBytes src*dest = d0
- lsl #3,d0 ; multiply d0 by 8 for size of dest bitMap
- _NewPtr clear ; allocate size of dest bitMap (a2 pts to it)
- move.l a0,baseaddr(a2) ; move contents of a0 to baseAddr field
- ; of dest bitMap structure
-
- ;-------------------------------------------------------------------------------
- ; a0 = baseAddr for our locals | d0 = rowbytes of srcMap
- ; a1 = points to bits of src bitMap | d1 = width/2 (source)
- ; a2 = ptr to dest bitMap | d2 = height/2 (source)
- ; a3 = dest bits | d3 = current word srcMap
- ; a4 = | d4 = copy of width of srcMap
- ; a5 = not used | d5 = current destMap word
- ; a6 = not used | d6 = insideLoop count (current bit)
- ; a7 = not used | d7 = rowBytes of dest bitMap
- ;-------------------------------------------------------------------------------
- ; ***********************************************************************
- ; * *
- ; * Start actual rotation of bitMaps *
- ; * *
- ; ***********************************************************************
- ; Assumptions:
- ; height of destination bitMap = rowBytes of srcMap
- ;
- ;
- ; Get the baseAddr for our locals into a0 - this will make our program much
- ; more readable as we will let the assembler do all the addr location calcs
- ; for us. The addresses will be a fixed number while the programs is
- ; (locked down) and running, therefore, there is no runtime penalty for
- ; doing this addr calculation
- ;
-
- lea localVars,a0
- ;
- ; initialize d0 to contain the pointer to the srcMap
- ;
- move.w rowbytes(a1),d0 ; get rowbytes of srcMap
-
- ;
- ; get regs pointing to bits
- ;
- move.l (a1),a1 ; a1 pts to BITS of src bitMap
- move.l (a2),a3 ; a3 pts to BITS of dest bitMap
-
- computeInitLowerLeft
- ;
- ; compute the lower left corner of the destMap - this maps to the upper left
- ; corner of the srcMap and will be used as base from which to offset into
- ; the dest map when we need to set a bit
- ;
- clr.l d1 ; clear d1
- move.w d0,d1 ; load rowBytes of srcMap
- ; (rowBytes of srcMap = ht of destMap)
- lsl.w #3,d1 ; multiply by 8 to get ht of destMap when rot'd
- mulu.w d7,d1 ; multiply by rowbytes(destMap) = #words in
- sub.w d7,d1 ; destMap less one row
- add.l a3,d1 ; add the computed offset to the baseAddr of destMap
- move.l d1,lowerLeft-localVars(a0) ; init lowerLeft
- ;
- ;-------------------------------------------------------------------------------
- ; a0 = baseAddr for our locals | d0 = rowbytes of srcMap
- ; a1 = points to bits of src bitMap | d1 = SCRATCH
- ; a2 = SCRATCH | d2 = colmCounter
- ; a3 = dest bits | d3 = current srcMap word
- ; a4 = SCRATCH | d4 = colmBitLoop counter
- ; a5 = not used | d5 = current word destMap
- ; a6 = not used | d6 = insideLoop count (current bit)
- ; a7 = not used | d7 = rowBytes of dest bitMap
- ;-------------------------------------------------------------------------------
- ;
-
- ; _Debugger;
-
- ; init wordCount to zero
- ;
- move.w #0,wordCount-localVars(a0) ; set wordCount to one before we start
- ;
- ; init colmLoop counter
- ;
- move.w d7,d2 ; get rowBytes(dest)
- lsr #1,d2 ; divide by 2 - d2 now contains the outer counter
- move.w d2,colmCount-localVars(a0) ; put the max value away for reference
- moveq.l #0,d2 ; set d2 to zero since we use it for the counter
-
- colmLoop
- ;
- ; this is the outside loop
- ;
- move.w #15,d4 ; init colmBitLoop counter to 15
- move.l lowerLeft-localVars(a0),currentWord-localVars(a0) ; init currentWord
-
- colmBitLoop
- ;
- ; this is the loop that does the bit counting in the destMap - it is really a
- ; misuse of the 'dbra' instruction since it is not an independent loop but it
- ; is a quite cheap method of doing our counting
- ;
-
- rowLoop
- ;
- ; loop across each row in the srcMap and keep count each time we do a row
- ; this 'rowCount' will used to compute the offset from 'lowerLeft'
- ;
- move.w (a1),d3 ; get a word to rotate into d3
- addq.w #2,wordCount-localVars(a0) ; add 1 for each word •••jdo•••
- moveq.l #0,d6 ; clear d6
- move.w #15,d6 ; initialize the inside (bit) loop counter
-
- innerLoop
- ;
- ; we will test each bit (15->0 ie. lt to rt) if it is set then we worry
- ; about going out and setting it in destMap otherwise we just increment the
- ; counters and test the next bit (cause we cleared them all at init)
- ;
- btst d6,d3 ; test bit pointed to in the current src word
- ; by the inner (bit) loop counter
- beq NoBitToChange ; if bits not set skip to next cause we cleared
- ; them at init of bitMap else set the corresponding
- ; bit before we bump the counter to the next bit
- ;
- ; bit needs to be set - get the word from memory, set bit and put it back
- ; this is very time consuming as each word is moved in/out of memory 16 times
- ; and a good place to look at for optimization - it probably means a complete
- ; rethink of the way we are doing this now
- ;
- nop
- movea.l currentWord-localVars(a0),a2 ; get addr of currentWord
- move.w (a2),d5 ; get currentWord
- bset d4,d5 ; set proper bit in currentWord
- move.w d5,(a2) ; put the currentWord word back
- ; into destMap (memory pt'd to by a3)
- nop
-
- noBitToChange
- ;
- ; bit was cleared at init of bitMap so we come here to increment the
- ; counters - we need to move over 1 bit in the srcWord and up 1 row in
- ; our destMap (which is always subtracting rowBytes
- ;
- sub.l d7,currentWord-localVars(a0) ; subtract rowBytes(destMap) from current word
- dbra d6,innerLoop ; keep looping (thru bits) till d6 = -1
- addq.l #2,a1 ; point to the next word in srcMap - this will take
- ; us all the way thru the srcMap as simple as that !
- ; Its the destMap that requires all the dang loops
- ; to get the addr of the corresponding word in the
- ; destMap
- doneWithSrcWord
- ;
- ; at this point we've just completed a word from the srcMap
- ;
- cmp wordCount-localVars(a0),d0 ; cmp wordCount to rowBytes-are we done with a row ?
- bne rowLoop ; no - do another word
-
- doneWithRow
- ;
- ; we just completed a row so add 2 to the count
- ;
- move.w #0,wordCount-localVars(a0) ; •••jdo••• reset wordCount to zero
-
- ;
- ; the following use of dbra keeps track of our destMap bit for us
- ;
- move.l lowerLeft-localVars(a0),currentWord-localVars(a0) ; re-init currentWord
- ; set the currentWord to the lowerLeft(current)
- ; lowerLeft is moved over (right) by a word each
- ; time we do a row in the srcMap
- dbra d4,colmBitLoop ; go thru the bits (15->0) in the
- ; destMap - then exit and do it
- ; again for rowBytes/2 times
-
- doneWithDestWord
- ;
- ; were done counting thru the bits of a destMap word - at this point we have
- ; actually finished a column in the destMap. The column is a multiple of
- ; 16 bits wide (and being at least 1 colm) and as tall as the destMap is
- ; (which is also equal to rowBytes of the srcMap)
- ;
- addq.l #2,lowerLeft-localVars(a0) ; this moves us into the next
- ; 'column' of bits in the destMap
- addq.w #1,d2 ; add 1 to the colmLoop counter
- cmp colmCount-localVars(a0),d2 ; are we done yet ?
- bne colmLoop ; no - do it again
- ; else we're done
- ;
- ; were done so lets do our clean-up/restore and go away gracefully
- ;
- cleanUpTime ; clean-up and get outta dodge
- movem.l (sp)+,d3-d7/a2-a5 ; restore registers
- unlk a6 ; clean up stack frame
- move.l (sp)+,a0 ; return address
- add.l #8,sp ; pop parameters off stack
- jmp (a0) ; bye y'all!
-
- ;
- ; set up our data storage area
- ;
- localVars ; the beginning of our local var storage area
- colmCount ds.w 1
- currentWord ds.l 1
- lowerLeft ds.l 1
- wordCount ds.w 1
-
- ENDP
-
- END
-
-
-